using DG.Tweening;
using Framework.Audio;
using Framework.Timer;
using Unity.Collections;
using UnityEngine;

namespace Framework.Audio
{

    [RequireComponent(typeof(AudioSource))]
    public class AudioTrack : MonoBehaviour
    {
        /// <summary>
        /// 音源
        /// </summary>
        private AudioSource _audioSource;
        public AudioSource AudioSource => this._audioSource;
        
        /// <summary>
        /// 音源名称
        /// </summary>
        private string  _audioClipName;
        public  string  AudioClipName   => this._audioClipName;
        /// <summary>
        /// 音源组
        /// </summary>
        [ReadOnly , SerializeField] private string _audioGroup;
        public string AudioGroup => this._audioGroup;
        /// <summary>
        /// 音源类型
        /// </summary>
        [ReadOnly , SerializeField] private AudioSourceType _AudioType;
        public AudioSourceType   AudioType   => this._AudioType;
        /// <summary>
        /// 总音量
        /// </summary>
        [ReadOnly , SerializeField] private float _BaseVolume;
        /// <summary>
        /// 总偏移量（包含global 和 group）
        /// </summary>
        [ReadOnly , SerializeField] private float _VolumeOffset;

        private float _LastVolumeOffset;
        private float _TargetVolumeOffset;


        
        /// <summary>
        /// 当前音量
        /// </summary>
        private float CurVolume => this._BaseVolume * this._VolumeOffset;
        
        /// <summary>
        /// 是否播放完毕
        /// </summary>
        public bool IsDone =>
            ( this._audioSource.clip == null) || (!this.IsPause && !this._audioSource.isPlaying);
        
        
        private TimeHandler         _timeHandler;
        private TimeHandler         _offsetTimeHandler;
        private TimeHandler         _grOffsetTimeHandler;
        public bool IsPause;
        
        /*/// <summary>
        /// 是否正在开启dotween动画
        /// </summary>
        private bool _isDotweening;

        private DOTween dt;*/
        /// <summary>
        /// 第一次被创建出来
        /// </summary>
        internal void OnCreate()
        {
            if (_audioSource != null)
            {
                return;
            }
            _audioSource = gameObject.AddComponent<AudioSource>();

            //EventCenter.AddListener(-1, OnSourceVolumeChange);
        }

        /// <summary>
        /// 初始化
        /// </summary>
        internal void Initial(AudioSourceType audioType)
        {
            this._AudioType               = audioType;
            this._audioSource.playOnAwake = false;
        }
        
        
        

        /// <summary>
        ///  播放指定音频
        /// </summary>
        /// <param name="clip"></param>
        /// <param name="audioGroup"></param>
        /// <param name="baseVolume"></param>
        /// <param name="globalVolume"></param>
        /// <param name="groupVolume"></param>
        /// <param name="outTime"></param>
        /// <param name="inTime"></param>
        /// <param name="isLoop"></param>
        public void PlayAudio( AudioClip clip,string audioGroup,float volumeOffset,float baseVolume=1f,  float inTime = 0, bool isLoop=false)
        {
            if ( _audioSource.clip==null)
            {
                this._audioSource.Stop();
                this._audioSource.clip = null;
            }
            
            _audioSource.clip          = clip;
            this._audioSource.loop     = isLoop;
            _audioClipName             = clip.name;
            this.name                  = clip.name;
            
            _audioGroup                = audioGroup;
            this._BaseVolume           = baseVolume;
            
            this._VolumeOffset       = volumeOffset;
            this._TargetVolumeOffset = volumeOffset;
            
            
            if (inTime == 0)
            {
                this._audioSource.volume = this.CurVolume;
            }
            else
            {
                this._audioSource.volume = 0;
                this._timeHandler = GameUpdateMgr.Instance.CreateTimer (inTime,
                    () => this._audioSource.volume = this.CurVolume,
                    f => this._audioSource.volume  = f * this.CurVolume);
            }
            this.IsPause = false;
            this._audioSource.Play ();
        }

        /// <summary>
        /// 暂停音频
        /// </summary>
        /// <param name="outTime"></param>
        public void PauseAudio (float outTime)
        {
            if (this.IsPause)
            {
                return;
            }

            this.IsPause = true;
            this._timeHandler?.Kill ();
            if (outTime == 0)
            {
                this._audioSource.Pause ();
            }
            else
            {
                this._timeHandler = GameUpdateMgr.Instance.CreateTimer (outTime, () => { this._audioSource.Pause (); },
                    f => { this._audioSource.volume = (1 - f) * this.CurVolume; });
            }
        }
        
        /// <summary>
        /// 恢复音频播放
        /// </summary>
        /// <param name="inTime"></param>
        public void ReplayAudio (float inTime)
        {
            if (!this.IsPause)
            {
                return;
            }

            this.IsPause = false;
            this._timeHandler?.Kill ();
            if (inTime == 0)
            {
                this._audioSource.volume = this.CurVolume;
            }
            else
            {
                this._timeHandler = GameUpdateMgr.Instance.CreateTimer (inTime,
                    () => { this._audioSource.volume = this.CurVolume; },
                    f => { this._audioSource.volume  = f * this.CurVolume; });
            }

            this._audioSource.UnPause ();
            
        }
        

        /// <summary>
        /// 直接关闭
        /// </summary>
        /// <param name="outTime"></param>
        public void Kill(float outTime=0)
        {
            this._timeHandler?.Kill ();
            this._offsetTimeHandler?.Kill ();
            this._grOffsetTimeHandler?.Kill ();
            if (outTime == 0)
            {
                this.Clear();
            }
            else
            {
                this._timeHandler = GameUpdateMgr.Instance.CreateTimer (outTime, this.Clear,
                    f => this._audioSource.volume = (1 - f) * this.CurVolume);
            }
        }
        
        
        
        #region 音量设置
        
        /// <summary>
        /// 设置基础音量（一般不变更，仅提供方法）
        /// </summary>
        /// <param name="volume">[0-1]</param>
        public void SetBaseVolume (float volume)
        {
            this._BaseVolume = volume;
            if (this._timeHandler?.IsDone ?? true)
            {
                // Debug.Log($"设置音量 {this.CurVolume}", this);
                this._audioSource.volume = this.CurVolume;
            }
        }
        
        
        /// <summary>
        /// 设置音频音量缩放系数
        /// </summary>
        /// <param name="volumeOffset">[0-1]</param>
        /// <param name="time"></param>
        public void SetVolumeOffset (float volumeOffset , float time = 0)
        {
            this._LastVolumeOffset   = _VolumeOffset;
            this._TargetVolumeOffset = volumeOffset;
            _offsetTimeHandler?.Kill ();
            _offsetTimeHandler = GameUpdateMgr.Instance.CreateTimer (time, () =>
            {
                _VolumeOffset = _TargetVolumeOffset;
                UpdateVolume ();
            }, f =>
            {
                _VolumeOffset = Mathf.Lerp (_LastVolumeOffset, _TargetVolumeOffset, f);
                UpdateVolume ();
            });

            void UpdateVolume ()
            {
                if (this._timeHandler?.IsDone ?? true)
                {
                    this._audioSource.volume = this.CurVolume;
                }
            }
        }
        

        #endregion
        
        
        /// <summary>
        /// 重置音频播放器
        /// </summary>
        internal void Clear ()
        {
            this._timeHandler?.Kill ();
            this._offsetTimeHandler?.Kill ();
            this._grOffsetTimeHandler?.Kill ();
#if UNITY_EDITOR
            this.name = $"[{this._AudioType}]Audio_Track";
#endif
            this._audioGroup = null;
            if (this._audioSource.isPlaying)
                this._audioSource.Stop ();
            this._audioSource.clip = null;
            //this._audioSourceHandler.OnAudioInvalid (this._AudioType, this._audioName);
            this._audioClipName                       = null;
            this._AudioType                           = AudioSourceType.None;
            this._audioSource.spatialBlend            = 0;
            this._audioSource.transform.localPosition = Vector3.zero;
            IsPause = false;
        }
        
    }
}